/*!
 * \file frreport_session_comm.c
 *
 * \brief 上报信息缓存共通管理
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 关联连接共通管理
 *
 * \version 2.0
 * \author yaohl
 * \date 2016/03/03
 *
 */

#include "frcomm.h"
#include "frhash2.h"
#include "frlog.h"
#include "frmem.h"

#include "module.h"

#include "frreport_session_comm.h"


int frreport_session_set(void* p_frame_ref, int i_l7_proto, pf_report_session_data_free pf_free)
{
    ApmContext *p_context = (ApmContext *)p_frame_ref;
    Frreport_session_ref *p_st_report_session_ref=NULL;
    Frlist_node *p_st_node=NULL;

    if(p_context == NULL
       || p_context->p_st_report_session_ref == NULL
       || p_context->p_st_report_session_ref->p_hash_hdr_data == NULL
       || p_context->p_st_report_session_ref->p_hash_hdr_node_free == NULL
       || p_context->p_st_report_session_ref->p_splock == NULL
       || pf_free == NULL)
        return FR_FAIL;

    p_st_report_session_ref = p_context->p_st_report_session_ref;
    pthread_spin_lock(p_st_report_session_ref->p_splock);
    //更新释放函数指针
    p_st_node = frhash2_getLong(p_st_report_session_ref->p_hash_hdr_node_free, i_l7_proto);
    if(p_st_node)
    {
        p_st_node->data = (void *)pf_free;
        pthread_spin_unlock(p_st_report_session_ref->p_splock);
        return FR_SUCC;
    }

    //保存释放函数指针
    p_st_node = frlist_node_create((void *)pf_free);
    if(p_st_node==NULL)
    {
        pthread_spin_unlock(p_st_report_session_ref->p_splock);
        return FR_FAIL;
    }

    frhash2_addLong(p_st_report_session_ref->p_hash_hdr_node_free, i_l7_proto, p_st_node);
    pthread_spin_unlock(p_st_report_session_ref->p_splock);
    return FR_SUCC;
}

int frreport_session_put(void* p_frame_ref, int i_l7_proto, const char *p_key, unsigned int ui_key_len, void *p_data)
{
    ApmContext *p_context = (ApmContext *)p_frame_ref;
    Frreport_session_ref *p_st_report_session_ref=NULL;
    Frlist_node *p_st_node=NULL;
    Frreport_session_data *p_session_data=NULL;

    if(p_context == NULL
       || p_context->p_st_report_session_ref == NULL
       || p_context->p_st_report_session_ref->p_hash_hdr_data == NULL
       || p_context->p_st_report_session_ref->p_hash_hdr_node_free == NULL
       || p_context->p_st_report_session_ref->p_splock == NULL
       || p_key == NULL || ui_key_len <= 0
       || p_data == NULL)
        return FR_FAIL;

    p_st_report_session_ref = p_context->p_st_report_session_ref;
    pthread_spin_lock(p_st_report_session_ref->p_splock);

    //确认释放函数指针是否已经存在
    p_st_node = frhash2_getLong(p_st_report_session_ref->p_hash_hdr_node_free, i_l7_proto);
    if(p_st_node == NULL)
    {
        pthread_spin_unlock(p_st_report_session_ref->p_splock);
        return FR_FAIL;
    }

    p_session_data = (Frreport_session_data *)frmalloc(sizeof(Frreport_session_data));
    if(p_session_data == NULL)
    {
        pthread_spin_unlock(p_st_report_session_ref->p_splock);
        return FR_FAIL;
    }
    p_session_data->i_l7_proto = i_l7_proto;
    gettimeofday (&p_session_data->st_timeval_upd, NULL);
    p_session_data->p_data = p_data;

    //数据保存
    p_st_node = frlist_node_create(p_session_data);
    if(p_st_node == NULL)
    {
        frfree(p_session_data);
        pthread_spin_unlock(p_st_report_session_ref->p_splock);
        return FR_FAIL;
    }
    frhash2_addStr(p_st_report_session_ref->p_hash_hdr_data, p_key, ui_key_len, p_st_node);
    pthread_spin_unlock(p_st_report_session_ref->p_splock);

    return FR_SUCC;
}

void *frreport_session_get(void* p_frame_ref, int i_l7_proto, const char *p_key, unsigned int ui_key_len)
{
    ApmContext *p_context = (ApmContext *)p_frame_ref;
    Frreport_session_ref *p_st_report_session_ref=NULL;
    Frlist_node *p_st_node=NULL;
    Frreport_session_data *p_session_data=NULL;
    void *p_data=NULL;

    if(p_context == NULL
       || p_context->p_st_report_session_ref == NULL
       || p_context->p_st_report_session_ref->p_hash_hdr_data == NULL
       || p_context->p_st_report_session_ref->p_hash_hdr_node_free == NULL
       || p_context->p_st_report_session_ref->p_splock == NULL
       || p_key == NULL || ui_key_len <= 0)
        return NULL;

    p_st_report_session_ref = p_context->p_st_report_session_ref;

    pthread_spin_lock(p_st_report_session_ref->p_splock);
    p_st_node = frhash2_getStr(p_st_report_session_ref->p_hash_hdr_data, p_key, ui_key_len);
    if(p_st_node)
        frhash2_apart(p_st_report_session_ref->p_hash_hdr_data, p_st_node);
    pthread_spin_unlock(p_st_report_session_ref->p_splock);

    if(p_st_node == NULL)
        return NULL;
    p_session_data = (Frreport_session_data *)FRLIST_GET_NODE_DATA(p_st_node);
    frlist_node_free2(&p_st_node);

    if(p_session_data == NULL)
        return NULL;

    p_data = p_session_data->p_data;
    frfree(p_session_data);
    return p_data;
}

